package com.fjut.zr.judge_system.VJ;

import com.fjut.zr.judge_system.POJO.PO.TVjResultPO;
import com.fjut.zr.judge_system.POJO.PO.TVjStatusPO;
import com.fjut.zr.judge_system.POJO.PO.TVjSubmitPO;
import com.fjut.zr.judge_system.Util.ApplicationContextHelper;
import com.fjut.zr.judge_system.Util.MyClient;
import com.fjut.zr.judge_system.VJ.Submitter.VJSubmitter;
import com.fjut.zr.judge_system.VJ.VJS.BaseVJ;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.springframework.core.env.Environment;

import java.util.ArrayList;
import java.util.List;

public class VjSubmitter implements Runnable{
    Environment env=ApplicationContextHelper.getBean(Environment.class);;
    public MyClient client = new MyClient(); //用这个网络客户端进行登录、提交等操作
    public TVjSubmitPO info;//正在处理的info
    int status;//忙碌状态与否0代表空闲1代表繁忙
    int ojid;//目标OJid
    int submitterID;//测评机ID
    Vjudge vj;
    String OjName;
    private  TVjSubmitPO submitInfoPO=new TVjSubmitPO();
    private TVjResultPO resultInfoPO=new TVjResultPO();
    private TVjStatusPO vjStatusPO=new TVjStatusPO();
    String url=env.getProperty("OJ.config.return.pathIp");

    private Thread selfThread = null;//获取测评机线程
    private String ojsrid;
    public VjSubmitter(int ojid, int id, Vjudge vj){
        OjName= VJSubmitter.vj_keys[ojid];
        this.ojid = ojid;
        status = 0;
        submitterID = id;
        this.vj = vj;
    }
    @Override
    public void run() {
        while(true){
            try {
                //读取队列执行
                vjStatusPO.setVjId(ojid);
                vjStatusPO.setOjName(OjName);
                vjStatusPO.setVjQueue(vj.queue.get(ojid).size());
                if(vj.queue.get(ojid).size()==0) {
                    System.out.println(OjName + submitterID+"队列为空等待提交");
                    vjStatusPO.setVjStatus("等待提交");
                }
                else {
                    vjStatusPO.setVjStatus("测评中");
                    System.out.println("+++++++++++++++++++" + OjName + submitterID + ":前方还有" + vj.queue.get(ojid).size() + "个提交数据");
                }
                this.info=vj.queue.get(ojid).take();//阻塞队列
                submitInfoPO.setRid(this.info.getRid());
                submitInfoPO.setOjId(this.info.getOjId());
                submitInfoPO.setPid(this.info.getPid());
                submitInfoPO.setLanguage(this.info.getLanguage());
                submitInfoPO.setCode(this.info.getCode());
                submitInfoPO.setJudgeStatus(1);
                //System.out.println("this.info:" + this.info);
                this.status = 1;
                go();
                ojsrid="->"+ojsrid;
                this.status=0;
            } catch (Exception e) {
                this.status=0;
                System.out.println(e);
                System.out.println(OjName+submitterID+":出错，10秒后重新运行");
                vjStatusPO.setVjStatus("出错了");
                submitInfoPO.setJudgeStatus(3);
                //线程暂停1秒
                try { Thread.sleep(10000); } catch (InterruptedException ignored) { }
            }
        }
    }
    public void go() {
        try{
            System.out.println(OjName+submitterID+":开始执行，正在第1次获取原rid");
            BaseVJ oj;
            oj = VJSubmitter.Vjs[ojid];//获取oj测评机
            String prid;
            int z = 0;
            do {
                z++;
                if(z>=10){
                    this.status = 0;
                    System.out.println(OjName+submitterID+":获取原rid出错");
                    return;
                }
                prid = oj.getRid(this);//获得原来的rid

                System.out.println(OjName+submitterID+":获得原来的rid:" + prid);
                //线程暂停1秒
                try { Thread.sleep(1000); } catch (InterruptedException ignored) { }

            } while(prid.equals("error"));
            String nrid;
            TVjResultPO resultInfo ;
            int num = 0;
            int k=2;
            do{
                while (oj.submit(this).equals("error")) {
                    num++;
                    if (num >= 10) {
                        System.out.println(OjName+submitterID+":doSubmit out time");
                        this.status=0;
                        System.out.println(OjName+submitterID+":第"+num+"次的提交出错，评测出错");
                        return;
                    }else{
                        System.out.println(OjName+submitterID+":第"+num+"次的提交出错，开始重试");
                    }
                    //线程暂停1秒
                    try { Thread.sleep(1000); } catch (InterruptedException ignored) { }
                }
                System.out.println(OjName+submitterID+":提交结束，开始获取评测结果");
                num = 0;
                do {
                    //线程暂停1秒
                    try { Thread.sleep(5000); } catch (InterruptedException ignored) { }
                    nrid = oj.getRid(this);
                    System.out.println(OjName+submitterID+":get rid "+num+"=" + nrid);
                    System.out.println(OjName+submitterID+":第"+num+"次获取rid="+nrid);
                    num++;
                    if (num == 5) break;//提交失败重新提交
                } while (nrid.equals("error")||nrid.equals(prid));
                k--;
            } while(num == 5 && k != 0);
            if (k == 0){
                submitInfoPO.setJudgeStatus(3);
                System.out.println(OjName+submitterID+":提交失败");
            } else {
                ojsrid = nrid;
                resultInfo = oj.getResult(this);
                //更新提交信息表
                if(resultInfo!=null) {
                    submitInfoPO.setJudgeStatus(2);
                      resultInfo.setRid(this.info.getRid());
                      resultInfo.setOjId(this.ojid);
                    try {
                    List<NameValuePair> formparams = new ArrayList<NameValuePair>();
                    formparams.add(new BasicNameValuePair("rid",this.info.getRid()));
                    formparams.add(new BasicNameValuePair("problem",resultInfo.getProblem()));
                    formparams.add(new BasicNameValuePair("result",resultInfo.getResult()));
                    formparams.add(new BasicNameValuePair("resultInfo",resultInfo.getResultDetail()));
                    formparams.add(new BasicNameValuePair("memory",resultInfo.getMemory()));
                    formparams.add(new BasicNameValuePair("time",resultInfo.getTime()));
                    formparams.add(new BasicNameValuePair("language",resultInfo.getLanguage()));
                    formparams.add(new BasicNameValuePair("codeLength",resultInfo.getCodelength()));
                        System.out.println(url);
                        System.out.println(resultInfo.toString());
                    System.out.println(client.Post(url+"fjut/judge_status/getJudgeResult", formparams));
                    }catch (Exception e)
                    {
                        System.out.println("请求错误"+e);
                    }


                }
                else {
                    submitInfoPO.setJudgeStatus(3);
                    System.out.println(resultInfo.toString());
                }

            }
            this.status=0;
        } catch(Exception e){
            submitInfoPO.setJudgeStatus(3);
            System.out.println(OjName+submitterID+":未知错误"+e);
            this.status=0;
        }
    }
    public void setSelfThread(Thread selfThread) {
        this.selfThread = selfThread;
    }

    public String getOjsrid() {
        return ojsrid;
    }
}
